package com.example.controller;

import com.example.entity.RestBean;
import com.example.service.ImageService;
import io.minio.errors.*;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 作者:xuSen
 * 日期2025/4/25 13:20
 * 该控制器类主要负责处理与图像获取相关的请求，通过与ImageService交互，
 * 从Minio存储中提取图像并返回给客户端，同时处理可能出现的各种错误情况。
 */
@Slf4j
@RestController
public class ObjectController {

    // 注入ImageService资源，用于处理与图像相关的操作，包括从Minio存储中获取图像等功能。
    @Resource
    private ImageService imageService;

    /**
     * 处理获取头像图像的请求
     * 此方法接收GET请求，尝试从Minio存储中提取图像，并将其直接返回给客户端。
     * 如果图像路径不符合预期或图像不存在，将向客户端返回404错误。
     *
     * @param request  HTTP请求对象，包含了客户端的请求信息，如请求路径等，用于获取图像路径。
     * @param response HTTP响应对象，用于向客户端发送图像数据，如果出现错误则发送错误信息。
     * @throws Exception 如果在图像处理过程中发生任何异常，如Minio操作错误、IO错误等，将抛出此异常。
     */
    @GetMapping("/images/**")
    public void imageFetch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 调用fetchImage方法处理图像获取逻辑
        this.fetchImage(request, response);
    }

    /**
     * 从Minio存储中提取图像并返回给客户端
     * 此方法首先解析请求路径以获取图像路径，然后根据该路径尝试从Minio存储中提取图像。
     * 如果图像路径过短或图像不存在，将向客户端返回404错误，否则将图像数据写入响应流。
     *
     * @param request  HTTP请求对象，用于获取图像路径信息，以便从Minio存储中定位图像。
     * @param response HTTP响应对象，用于向客户端发送图像数据或错误信息，根据图像获取的结果进行相应设置。
     * @throws Exception 如果在图像处理过程中发生任何异常，如Minio操作错误、IO错误等，将抛出此异常。
     */
    private void fetchImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 从请求路径中提取图像路径，这里假设路径的前7个字符是"/images/"，所以截取从第7个字符开始的部分作为图像路径。
        String imagePath = request.getServletPath().substring(7);
        // 获取响应输出流，用于向客户端发送图像数据或错误信息。
        ServletOutputStream stream = response.getOutputStream();
        // 检查图像路径长度，如果过短则认为是无效请求，返回404错误。
        // 这里的判断依据是认为有效图像路径长度应该大于13个字符，具体长度判断可根据实际情况调整。
        if (imagePath.length() <= 13) {
            // 设置响应状态码为404，表示资源未找到。
            response.setStatus(404);
            // 将错误信息封装成RestBean对象并转换为字符串形式，通过输出流发送给客户端。
            stream.println(RestBean.failure(404, "图片不存在").toString());
        } else {
            try {
                // 调用ImageService的fetchImageFromMinio方法，从Minio存储中提取图像，并将图像数据写入输出流。
                imageService.fetchImageFromMinio(stream, imagePath);
                // 设置响应头，指示浏览器缓存图像，缓存时间为30天（2592000秒）。
                response.setHeader("Cache-Control", "max-age=2592000");
                // 设置响应头，指定响应内容的类型为JPEG图像。
                response.setHeader("Content-Type", "image/jpg");
            } catch (ErrorResponseException e) {
                // 处理从Minio存储提取图像时发生的错误响应异常。
                // 如果Minio返回的响应状态码为404，表明图像不存在，向客户端返回404错误。
                if (e.response().code() == 404) {
                    response.setStatus(404);
                    stream.println(RestBean.failure(404, "图片不存在").toString());
                } else {
                    // 如果发生其他错误，记录错误日志，以便后续排查问题。
                    log.error("从Minio获取图片异常" + e.getMessage(), e);
                }
            }
        }
    }
}